package com.zboin.framework.interceptor;

import com.alibaba.fastjson2.JSONObject;
import com.auth0.jwt.exceptions.InvalidClaimException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.zboin.common.domain.AjaxResult;
import com.zboin.domain.LoginUser;
import com.zboin.framework.serve.TokenServe;
import com.zboin.utils.UserUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;

import java.io.IOException;
import java.io.PrintWriter;

/**
 * @author zhboom
 * @date 2025/6/10 21:51
 */
@Slf4j
public class AuthInterceptor implements HandlerInterceptor {

    private static final String TOKEN_HEADER = "Authorization ";

    private final TokenServe tokenServe;

    public AuthInterceptor(TokenServe tokenServe) {
        this.tokenServe = tokenServe;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.trace("auth interceptor start");
        String token = tokenServe.getToken(request);
        if (!StringUtils.hasText(token)) {
            response(response, HttpStatus.UNAUTHORIZED.value(), "Unauthorized, please login.");
            return false;
        }
        try {
            String nToken = tokenServe.validToken(token);
            // 刷新 token，将新的 token 放在 response header 中
            if (nToken != null) {
                response.setHeader(TOKEN_HEADER, nToken);
            }
        } catch (JWTVerificationException e) {
            log.error(e.getMessage(), e);
            if (e instanceof InvalidClaimException) {
                response(response, HttpStatus.FORBIDDEN.value(), e.getMessage());
            }
            else if (e instanceof TokenExpiredException) {
                response(response, HttpStatus.UNAUTHORIZED.value(), e.getMessage());
            }
            return false;
        }

        LoginUser loginUser = tokenServe.getLoginUser(token);
        UserUtil.setLoginUser(loginUser);
        log.trace("auth interceptor finished.");
        return true;
    }

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        UserUtil.clearLoginUser();
        log.trace("end request and clear user cache");
    }

    private void response(HttpServletResponse response, int status, String message) throws IOException {
        // 设置响应码
        response.setStatus(HttpStatus.OK.value());
        // 设置响应头
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        // 设置头部信息
        response.setHeader("Cache-Control", "no-cache, must-revalidate");

        try (PrintWriter writer = response.getWriter()) {
            AjaxResult error = AjaxResult.error(status, message);
            writer.write(JSONObject.toJSONString(error));
            writer.flush();
        }
    }
}
